<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="keywords" content="Hexo Theme Redefine">
    
    <meta name="author" content="xiaoeryu">
    <!-- preconnect -->
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>

    
    <!--- Seo Part-->
    
    <link rel="canonical" href="https://xiaoeeyu.github.io/2023/08/24/加壳app运行流程和classloader修正/"/>
    <meta name="robots" content="index,follow">
    <meta name="googlebot" content="index,follow">
    <meta name="revisit-after" content="1 days">
    
    
    
        
        <meta name="description" content="本章内容主要基于分析Android 8.0源码，来学习APP的启动流程和APP加壳原理以及运行流程，以及写代码怎么去从sd卡加载其它dex中的Activity，不涉及加密解密的操作。">
<meta property="og:type" content="article">
<meta property="og:title" content="加壳APP运行流程和ClassLoader修正">
<meta property="og:url" content="https://xiaoeeyu.github.io/2023/08/24/%E5%8A%A0%E5%A3%B3APP%E8%BF%90%E8%A1%8C%E6%B5%81%E7%A8%8B%E5%92%8CClassLoader%E4%BF%AE%E6%AD%A3/index.html">
<meta property="og:site_name" content="xiaoeryu">
<meta property="og:description" content="本章内容主要基于分析Android 8.0源码，来学习APP的启动流程和APP加壳原理以及运行流程，以及写代码怎么去从sd卡加载其它dex中的Activity，不涉及加密解密的操作。">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://xiaoeeyu.github.io/2023/08/24/%E5%8A%A0%E5%A3%B3APP%E8%BF%90%E8%A1%8C%E6%B5%81%E7%A8%8B%E5%92%8CClassLoader%E4%BF%AE%E6%AD%A3/image-20230824173255564.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2023/08/24/%E5%8A%A0%E5%A3%B3APP%E8%BF%90%E8%A1%8C%E6%B5%81%E7%A8%8B%E5%92%8CClassLoader%E4%BF%AE%E6%AD%A3/image-20230824174127453.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2023/08/24/%E5%8A%A0%E5%A3%B3APP%E8%BF%90%E8%A1%8C%E6%B5%81%E7%A8%8B%E5%92%8CClassLoader%E4%BF%AE%E6%AD%A3/image-20230824175216003.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2023/08/24/%E5%8A%A0%E5%A3%B3APP%E8%BF%90%E8%A1%8C%E6%B5%81%E7%A8%8B%E5%92%8CClassLoader%E4%BF%AE%E6%AD%A3/image-20230825163132654.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2023/08/24/%E5%8A%A0%E5%A3%B3APP%E8%BF%90%E8%A1%8C%E6%B5%81%E7%A8%8B%E5%92%8CClassLoader%E4%BF%AE%E6%AD%A3/image-20230824220114889.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2023/08/24/%E5%8A%A0%E5%A3%B3APP%E8%BF%90%E8%A1%8C%E6%B5%81%E7%A8%8B%E5%92%8CClassLoader%E4%BF%AE%E6%AD%A3/image-20230824215203666.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2023/08/24/%E5%8A%A0%E5%A3%B3APP%E8%BF%90%E8%A1%8C%E6%B5%81%E7%A8%8B%E5%92%8CClassLoader%E4%BF%AE%E6%AD%A3/image-20230824222103300.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2023/08/24/%E5%8A%A0%E5%A3%B3APP%E8%BF%90%E8%A1%8C%E6%B5%81%E7%A8%8B%E5%92%8CClassLoader%E4%BF%AE%E6%AD%A3/image-20230824223243415.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2023/08/24/%E5%8A%A0%E5%A3%B3APP%E8%BF%90%E8%A1%8C%E6%B5%81%E7%A8%8B%E5%92%8CClassLoader%E4%BF%AE%E6%AD%A3/image-20230824223416570.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2023/08/24/%E5%8A%A0%E5%A3%B3APP%E8%BF%90%E8%A1%8C%E6%B5%81%E7%A8%8B%E5%92%8CClassLoader%E4%BF%AE%E6%AD%A3/image-20230824223613663.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2023/08/24/%E5%8A%A0%E5%A3%B3APP%E8%BF%90%E8%A1%8C%E6%B5%81%E7%A8%8B%E5%92%8CClassLoader%E4%BF%AE%E6%AD%A3/image-20230824223840687.png">
<meta property="article:published_time" content="2023-08-24T08:41:02.000Z">
<meta property="article:modified_time" content="2023-08-26T14:39:52.184Z">
<meta property="article:author" content="xiaoeryu">
<meta property="article:tag" content="学习笔记">
<meta property="article:tag" content="Android加壳">
<meta property="article:tag" content="加壳和运行时的机制">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://xiaoeeyu.github.io/2023/08/24/%E5%8A%A0%E5%A3%B3APP%E8%BF%90%E8%A1%8C%E6%B5%81%E7%A8%8B%E5%92%8CClassLoader%E4%BF%AE%E6%AD%A3/image-20230824173255564.png">
    
    
    <!--- Icon Part-->
    <link rel="icon" type="image/png" href="/images/rabete.jpg" sizes="192x192">
    <link rel="apple-touch-icon" sizes="180x180" href="/images/rabete.jpg">
    <meta name="theme-color" content="#A31F34">
    <link rel="shortcut icon" href="/images/rabete.jpg">
    <!--- Page Info-->
    
    <title>
        
            加壳APP运行流程和ClassLoader修正 | xiaoeryu
        
    </title>

    
<link rel="stylesheet" href="/fonts/Chillax/chillax.css">


    <!--- Inject Part-->
    

    
<link rel="stylesheet" href="/css/style.css">


    
        
<link rel="stylesheet" href="/css/build/tailwind.css">

    

    
<link rel="stylesheet" href="/fonts/GeistMono/geist-mono.css">

    
<link rel="stylesheet" href="/fonts/Geist/geist.css">

    <!--- Font Part-->
    
    
    
    
    
    

    <script id="hexo-configurations">
    window.config = {"hostname":"xiaoeeyu.github.io","root":"/","language":"zh-CN","path":"search.xml"};
    window.theme = {"articles":{"style":{"font_size":"16px","line_height":1.5,"image_border_radius":"14px","image_alignment":"center","image_caption":false,"link_icon":true,"delete_mask":false,"title_alignment":"left","headings_top_spacing":{"h1":"3.2rem","h2":"2.4rem","h3":"1.9rem","h4":"1.6rem","h5":"1.4rem","h6":"1.3rem"}},"word_count":{"enable":true,"count":true,"min2read":true},"author_label":{"enable":true,"auto":false,"list":[]},"code_block":{"copy":true,"style":"mac","highlight_theme":{"light":"github","dark":"vs2015"},"font":{"enable":false,"family":null,"url":null}},"toc":{"enable":true,"max_depth":4,"number":false,"expand":true,"init_open":true},"copyright":{"enable":true,"default":"cc_by_nc_sa"},"lazyload":true,"pangu_js":false,"recommendation":{"enable":false,"title":"推荐阅读","limit":3,"mobile_limit":2,"placeholder":"/images/ball-0101.jpg","skip_dirs":[]}},"colors":{"primary":"#A31F34","secondary":null,"default_mode":"light"},"global":{"fonts":{"chinese":{"enable":false,"family":null,"url":null},"english":{"enable":false,"family":null,"url":null},"title":{"enable":false,"family":null,"url":null}},"content_max_width":"1000px","sidebar_width":"210px","hover":{"shadow":true,"scale":false},"scroll_progress":{"bar":false,"percentage":true},"website_counter":{"url":"https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js","enable":true,"site_pv":true,"site_uv":true,"post_pv":true},"single_page":true,"preloader":{"enable":false,"custom_message":null},"open_graph":true,"google_analytics":{"enable":false,"id":null}},"home_banner":{"enable":true,"style":"fixed","image":{"light":"/images/wallhaven-jxl31y.png","dark":"/images/wallhaven-o5762l.png"},"title":"XIAOERYU","subtitle":{"text":["明心见性，拨云见日","Don't wait, to create"],"hitokoto":{"enable":false,"show_author":false,"api":"https://v1.hitokoto.cn"},"typing_speed":100,"backing_speed":80,"starting_delay":500,"backing_delay":1500,"loop":true,"smart_backspace":true},"text_color":{"light":"#fff","dark":"#d1d1b6"},"text_style":{"title_size":"2.8rem","subtitle_size":"1.5rem","line_height":1.2},"custom_font":{"enable":false,"family":null,"url":null},"social_links":{"enable":true,"style":"default","links":{"github":"https://github.com/xiaoeeyu","instagram":null,"zhihu":null,"twitter":null,"email":"xiaoeryu@163.com"},"qrs":{"weixin":null}}},"plugins":{"feed":{"enable":false},"aplayer":{"enable":false,"type":"fixed","audios":[{"name":null,"artist":null,"url":null,"cover":null,"lrc":null}]},"mermaid":{"enable":false,"version":"9.3.0"}},"version":"2.8.2","navbar":{"auto_hide":false,"color":{"left":"#f78736","right":"#367df7","transparency":35},"width":{"home":"1200px","pages":"1000px"},"links":{"Home":{"path":"/","icon":"fa-regular fa-house"},"Archives":{"path":"/archives","icon":"fa-regular fa-archive"}},"search":{"enable":true,"preload":true}},"page_templates":{"friends_column":2,"tags_style":"blur"},"home":{"sidebar":{"enable":true,"position":"left","first_item":"menu","announcement":null,"show_on_mobile":true,"links":null},"article_date_format":"auto","excerpt_length":200,"categories":{"enable":true,"limit":3},"tags":{"enable":true,"limit":3}},"footerStart":"2022/8/17 11:45:14"};
    window.lang_ago = {"second":"%s 秒前","minute":"%s 分钟前","hour":"%s 小时前","day":"%s 天前","week":"%s 周前","month":"%s 个月前","year":"%s 年前"};
    window.data = {"masonry":false};
  </script>
    
    <!--- Fontawesome Part-->
    
<link rel="stylesheet" href="/fontawesome/fontawesome.min.css">

    
<link rel="stylesheet" href="/fontawesome/brands.min.css">

    
<link rel="stylesheet" href="/fontawesome/solid.min.css">

    
<link rel="stylesheet" href="/fontawesome/regular.min.css">

    
    
    
    
<meta name="generator" content="Hexo 6.3.0">
<style>.github-emoji { position: relative; display: inline-block; width: 1.2em; min-height: 1.2em; overflow: hidden; vertical-align: top; color: transparent; }  .github-emoji > span { position: relative; z-index: 10; }  .github-emoji img, .github-emoji .fancybox { margin: 0 !important; padding: 0 !important; border: none !important; outline: none !important; text-decoration: none !important; user-select: none !important; cursor: auto !important; }  .github-emoji img { height: 1.2em !important; width: 1.2em !important; position: absolute !important; left: 50% !important; top: 50% !important; transform: translate(-50%, -50%) !important; user-select: none !important; cursor: auto !important; } .github-emoji-fallback { color: inherit; } .github-emoji-fallback img { opacity: 0 !important; }</style>
</head>



<body>
	<div class="progress-bar-container">
	

	
	<span class="pjax-progress-bar"></span>
	<!--        <span class="swup-progress-icon">-->
	<!--            <i class="fa-solid fa-circle-notch fa-spin"></i>-->
	<!--        </span>-->
	
</div>

<main class="page-container" id="swup">

	

	<div class="main-content-container flex flex-col justify-between min-h-dvh">
		<div class="main-content-header">
			<header class="navbar-container px-6 md:px-12">
    <div class="navbar-content transition-navbar ">
        <div class="left">
            
                <a class="logo-image h-8 w-8 sm:w-10 sm:h-10 mr-3" href="/">
                    <img src="/images/rabete.jpg" class="w-full h-full rounded-sm">
                </a>
            
            <a class="logo-title" href="/">
                
                xiaoeryu
                
            </a>
        </div>

        <div class="right">
            <!-- PC -->
            <div class="desktop">
                <ul class="navbar-list">
                    
                        
                            

                            <li class="navbar-item">
                                <!-- Menu -->
                                <a class=""
                                   href="/"
                                        >
                                    <i class="fa-regular fa-house fa-fw"></i>
                                    首页
                                    
                                </a>

                                <!-- Submenu -->
                                
                            </li>
                    
                        
                            

                            <li class="navbar-item">
                                <!-- Menu -->
                                <a class=""
                                   href="/archives"
                                        >
                                    <i class="fa-regular fa-archive fa-fw"></i>
                                    归档
                                    
                                </a>

                                <!-- Submenu -->
                                
                            </li>
                    
                    
                        <li class="navbar-item search search-popup-trigger">
                            <i class="fa-solid fa-magnifying-glass"></i>
                        </li>
                    
                </ul>
            </div>
            <!-- Mobile -->
            <div class="mobile">
                
                    <div class="icon-item search search-popup-trigger"><i class="fa-solid fa-magnifying-glass"></i>
                    </div>
                
                <div class="icon-item navbar-bar">
                    <div class="navbar-bar-middle"></div>
                </div>
            </div>
        </div>
    </div>

    <!-- Mobile sheet -->
    <div class="navbar-drawer h-dvh w-full absolute top-0 left-0 bg-background-color flex flex-col justify-between">
        <ul class="drawer-navbar-list flex flex-col px-4 justify-center items-start">
            
                
                    

                    <li class="drawer-navbar-item text-base my-1.5 flex flex-col w-full">
                        
                        <a class="py-1.5 px-2 flex flex-row items-center justify-between gap-1 hover:!text-primary active:!text-primary text-2xl font-semibold group border-b border-border-color hover:border-primary w-full "
                           href="/"
                        >
                            <span>
                                首页
                            </span>
                            
                                <i class="fa-regular fa-house fa-sm fa-fw"></i>
                            
                        </a>
                        

                        
                    </li>
            
                
                    

                    <li class="drawer-navbar-item text-base my-1.5 flex flex-col w-full">
                        
                        <a class="py-1.5 px-2 flex flex-row items-center justify-between gap-1 hover:!text-primary active:!text-primary text-2xl font-semibold group border-b border-border-color hover:border-primary w-full "
                           href="/archives"
                        >
                            <span>
                                归档
                            </span>
                            
                                <i class="fa-regular fa-archive fa-sm fa-fw"></i>
                            
                        </a>
                        

                        
                    </li>
            

            
            
        </ul>

        <div class="statistics flex justify-around my-2.5">
    <a class="item tag-count-item flex flex-col justify-center items-center w-20" href="/tags">
        <div class="number text-2xl sm:text-xl text-second-text-color font-semibold">92</div>
        <div class="label text-third-text-color text-sm">标签</div>
    </a>
    <a class="item tag-count-item flex flex-col justify-center items-center w-20" href="/categories">
        <div class="number text-2xl sm:text-xl text-second-text-color font-semibold">14</div>
        <div class="label text-third-text-color text-sm">分类</div>
    </a>
    <a class="item tag-count-item flex flex-col justify-center items-center w-20" href="/archives">
        <div class="number text-2xl sm:text-xl text-second-text-color font-semibold">112</div>
        <div class="label text-third-text-color text-sm">文章</div>
    </a>
</div>
    </div>

    <div class="window-mask"></div>

</header>


		</div>

		<div class="main-content-body transition-fade-up">
			

			<div class="main-content">
				<div class="post-page-container flex relative justify-between box-border w-full h-full">
	<div class="article-content-container">

		<div class="article-title relative w-full">
			
			<div class="w-full flex items-center pt-6 justify-start">
				<h1 class="article-title-regular text-second-text-color tracking-tight text-4xl md:text-6xl font-semibold px-2 sm:px-6 md:px-8 py-3">加壳APP运行流程和ClassLoader修正</h1>
			</div>
			
		</div>

		
		<div class="article-header flex flex-row gap-2 items-center px-2 sm:px-6 md:px-8">
			<div class="avatar w-[46px] h-[46px] flex-shrink-0 rounded-medium border border-border-color p-[1px]">
				<img src="/images/rabete.jpg">
			</div>
			<div class="info flex flex-col justify-between">
				<div class="author flex items-center">
					<span class="name text-default-text-color text-lg font-semibold">xiaoeryu</span>
					
					<span class="author-label ml-1.5 text-xs px-2 py-0.5 rounded-small text-third-text-color border border-shadow-color-1">Lv5</span>
					
				</div>
				<div class="meta-info">
					<div class="article-meta-info">
    <span class="article-date article-meta-item">
        <i class="fa-regular fa-pen-fancy"></i>&nbsp;
        <span class="desktop">2023-08-24 16:41:02</span>
        <span class="mobile">2023-08-24 16:41:02</span>
        <span class="hover-info">创建</span>
    </span>
    
        <span class="article-date article-meta-item">
            <i class="fa-regular fa-wrench"></i>&nbsp;
            <span class="desktop">2023-08-26 22:39:52</span>
            <span class="mobile">2023-08-26 22:39:52</span>
            <span class="hover-info">更新</span>
        </span>
    

    
        <span class="article-categories article-meta-item">
            <i class="fa-regular fa-folders"></i>&nbsp;
            <ul>
                
                
                    
                        
                        <li>
                            <a href="/categories/Android%E9%80%86%E5%90%91/">Android逆向</a>&nbsp;
                        </li>
                    
                    
                
            </ul>
        </span>
    
    
        <span class="article-tags article-meta-item">
            <i class="fa-regular fa-tags"></i>&nbsp;
            <ul>
                
                    <li>
                        <a href="/tags/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/">学习笔记</a>&nbsp;
                    </li>
                
                    <li>
                        | <a href="/tags/Android%E5%8A%A0%E5%A3%B3/">Android加壳</a>&nbsp;
                    </li>
                
                    <li>
                        | <a href="/tags/%E5%8A%A0%E5%A3%B3%E5%92%8C%E8%BF%90%E8%A1%8C%E6%97%B6%E7%9A%84%E6%9C%BA%E5%88%B6/">加壳和运行时的机制</a>&nbsp;
                    </li>
                
            </ul>
        </span>
    

    
    
    
    
        <span class="article-pv article-meta-item">
            <i class="fa-regular fa-eye"></i>&nbsp;<span id="busuanzi_value_page_pv"></span>
        </span>
    
</div>

				</div>
			</div>
		</div>
		

		


		<div class="article-content markdown-body px-2 sm:px-6 md:px-8 pb-8">
			<p>本章内容主要基于分析Android 8.0源码，来学习APP的启动流程和APP加壳原理以及运行流程，以及写代码怎么去从sd卡加载其它dex中的Activity，不涉及加密解密的操作。</p>
<span id="more"></span>



<h3 id="app启动流程"><a href="#app启动流程" class="headerlink" title="app启动流程"></a>app启动流程</h3><img lazyload="" src="/images/loading.svg" data-src="/2023/08/24/%E5%8A%A0%E5%A3%B3APP%E8%BF%90%E8%A1%8C%E6%B5%81%E7%A8%8B%E5%92%8CClassLoader%E4%BF%AE%E6%AD%A3/image-20230824173255564.png" class="" title="image-20230824173255564">

<ul>
<li>通过Zygote进程最终进入到app进程的世界，ActivityThread.main()是进入app进程世界的大门。只有通过这个函数之后，我们才进入到一个加壳app自己的代码当中。</li>
</ul>
<p><strong>源码网址：</strong></p>
<ul>
<li><a class="link" target="_blank" rel="noopener" href="http://androidxref.com/">国外<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a></li>
<li><a class="link" target="_blank" rel="noopener" href="http://aospxref.com/">国内<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a></li>
</ul>
<h4 id="ActivityThread的源代码"><a href="#ActivityThread的源代码" class="headerlink" title="ActivityThread的源代码"></a>ActivityThread的源代码</h4><p>ActivityThread的源代码在frameworks当中</p>
<img lazyload="" src="/images/loading.svg" data-src="/2023/08/24/%E5%8A%A0%E5%A3%B3APP%E8%BF%90%E8%A1%8C%E6%B5%81%E7%A8%8B%E5%92%8CClassLoader%E4%BF%AE%E6%AD%A3/image-20230824174127453.png" class="" title="image-20230824174127453">

<ul>
<li><p>通过Zygote进程最终进入到APP进程的世界，ActivityThread.main()是进入app进程世界的大门。只有通过这个函数之后，我们才进入到一个加壳app自己的代码当中。ActivityThread还有一个静态函数currentActivityThread那我们就可以通过它来获取到进程当中的ActivityThread实例进而获取到Activity当中的一些很重要的变量。</p>
<img lazyload="" src="/images/loading.svg" data-src="/2023/08/24/%E5%8A%A0%E5%A3%B3APP%E8%BF%90%E8%A1%8C%E6%B5%81%E7%A8%8B%E5%92%8CClassLoader%E4%BF%AE%E6%AD%A3/image-20230824175216003.png" class="" title="image-20230824175216003">
</li>
<li><p>对于ActivityThread这个类，其中的sCurrentActivityThread静态变量用于全局保存创建的ActivityThread实例,</p>
<pre><code class="java">javaprivate static volatile ActivityThread sCurrentActivityThread;
</code></pre>
<p>同时还提供了<code>public static ActivityThread currentActivityThread()</code>这个静态函数用于获取当前虚拟机创建的ActivityThread实例。ActivityThread.main()函数是java中app启动的入口main()函数，这里会启动主消息循环，并创建ActivityThread实例，之后调用thread.attach(false)完成一系列初始化准备工作，并完成全局静态变量sCurrentActivityThread的初始化。</p>
<pre><code class="java">private void attach(boolean system) {
    sCurrentActivityThread = this;
    ...
}

--------------------------------------------------

public static void main(String[] args) {
    ...
    // 创建Looper对象，创建MessageQueue对象
    Looper.prepareMainLooper();

    // 创建自己的ActivityThread对象
    ActivityThread thread = new ActivityThread();
    thread.attach(false);

    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }

    if (false) {
        Looper.myLooper().setMessageLogging(new
                LogPrinter(Log.DEBUG, "ActivityThread"));
    }

    // End of event ActivityThreadMain.
    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    Looper.loop();

    throw new RuntimeException("Main thread loop unexpectedly exited");
}
</code></pre>
<p>之后主线进程进入消息循环，等待接收来自系统的消息。当收到系统发送来的bindapplication的进程间调用时，调用函数handlebindapplication来处理该请求</p>
<pre><code class="java">public void handleMessage(Message msg) {
    
    ...
    // 处理bindApplication调用
    case BIND_APPLICATION:
    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
    AppBindData data = (AppBindData)msg.obj;
    handleBindApplication(data);
    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    
    ...
        
}
-------------------------------------------------------------
// 定义不可修改&amp;继承的LoadedApk对象    
public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai,
    CompatibilityInfo compatInfo) {
    return getPackageInfo(ai, compatInfo, null, false, true, false);
}

-------------------------------------------------------------
private void handleBindApplication(AppBindData data) {
    //step 1: 创建LoadedApk对象
    data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
    ...
    //step 2: 创建ContextImpl对象;
    final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
 
    //step 3: 创建Instrumentation
    mInstrumentation = new Instrumentation();
 
    //step 4: 创建Application对象;在makeApplication函数中调用了newApplication，在该函数中又调用了app.attach(context)，在attach函数中调用了Application.attachBaseContext函数
    Application app = data.info.makeApplication(data.restrictedBackupMode, null);
    mInitialApplication = app;
 
    //step 5: 安装providers
    List&lt;ProviderInfo&gt; providers = data.providers;
    installContentProviders(app, providers);
 
    //step 6: 执行Application.Create回调
    mInstrumentation.callApplicationOnCreate(app);
</code></pre>
<p>在handleBindApplication函数中第一次进入了app的代码世界，该函数功能启动一个application，并把系统收集到的apk组件等相关信息绑定到application里，在创建完application对象后，接着调用了application的attachBaseContext方法，之后调用了application的onCreate函数。由此可以发现，<strong>app的Application类中的attachBaseContext和onCreate这两个函数是最先获取执行权进行代码执行的。这也是为什么各家的加固工具的主要逻辑都是通过替换app入口Application，并亲自实现这两个函数</strong>，在这两个函数中进行代码的脱壳以及执行权交付的原因。</p>
</li>
</ul>
<h3 id="APP加壳原理以及运行流程"><a href="#APP加壳原理以及运行流程" class="headerlink" title="APP加壳原理以及运行流程"></a>APP加壳原理以及运行流程</h3><p>从前面的分析可以得出一个结论，app最先获得执行权限的是app中声明的Application类中的attachBaseContext和onCreate函数。因此，壳想要完成应用中加固代码的解密以及应用执行权的交付就都是在这两个函数上做文章。下图大致讲了加壳应用的运行流程。</p>
<img lazyload="" src="/images/loading.svg" data-src="/2023/08/24/%E5%8A%A0%E5%A3%B3APP%E8%BF%90%E8%A1%8C%E6%B5%81%E7%A8%8B%E5%92%8CClassLoader%E4%BF%AE%E6%AD%A3/image-20230825163132654.png" class="" title="image-20230825163132654">

<p>当壳函数attachBaseContext和onCreate中执行完加密的dex文件的解密后，通过自定义的ClassLoader在内存中加载解密后的dex文件。为了解决后续应用在加载执行解密后的dex文件中的Class和Method的问题，接下来就是通过利用java的反射修复一系列需要用到的变量。其中最为重要的一个变量就是应用运行中的ClassLoader，只有ClassLoader被修正后，应用才能够正常的加载并调用dex中的类和方法，否则的话由于ClassLoader的双亲委派机制，最终会报ClassnotFound异常，应用崩溃退出。ClassLoader是一个至关重要的变量，所有的应用中加载的dex文件最终都在app的ClassLoader中。</p>
<p>因此，只要获取到加固应用最终通过反射设置后的ClassLoader，我们就可以通过一系列反射最终获取到当前应用所加载的解密后的内存中的Dex文件。</p>
<p>随着加壳技术的发展，为了对抗dex整体加固容易被内存dump来得到原始dex的问题，各加固厂商又结合hook技术，通过hook dex文件中类和方法加载执行过程中的关键流程，来实现在函数执行前才进行解密操作的指令抽取的解决方案。此时，就算是对内存中的dex整体进行了dump，但是由于其方法的最为重要的函数体中的指令被加密，导致无法对相关的函数进行脱壳。由此Fupk3诞生了，该脱壳工具通过欺骗壳而主动调用dex中的各个函数，完成调用流程，让壳主动解密对应method的指令区域，从而完成对指令抽取型壳的脱壳。</p>
<h4 id="分析源码并写代码加载其它dex中Activity"><a href="#分析源码并写代码加载其它dex中Activity" class="headerlink" title="分析源码并写代码加载其它dex中Activity"></a>分析源码并写代码加载其它dex中Activity</h4><ol>
<li><p>先通过反射获取到ActivityThread，它是一个单例模式，可以获取到app进程当中仅有的ActivityThread的实例</p>
</li>
<li><p>接下来可以通过反射获取到mPackages的ArrayMap对象（这里的ArrayMap用于存储已加载的应用程序包的信息）</p>
<img lazyload="" src="/images/loading.svg" data-src="/2023/08/24/%E5%8A%A0%E5%A3%B3APP%E8%BF%90%E8%A1%8C%E6%B5%81%E7%A8%8B%E5%92%8CClassLoader%E4%BF%AE%E6%AD%A3/image-20230824220114889.png" class="" title="image-20230824220114889">
</li>
<li><p>通过mPackages获取到loadApk：（LoadedApk是Android中表示已加载应用程序包信息的类，它包含了应用程序的资源、类加载器、类信息等，其中就保存有我们加载app组件的mClassLoader）</p>
<img lazyload="" src="/images/loading.svg" data-src="/2023/08/24/%E5%8A%A0%E5%A3%B3APP%E8%BF%90%E8%A1%8C%E6%B5%81%E7%A8%8B%E5%92%8CClassLoader%E4%BF%AE%E6%AD%A3/image-20230824215203666.png" class="" title="image-20230824215203666">
</li>
<li><p>通过LoadedApk获取到mClassLoader字段（这就是接下来app运行过程中用于加载相关的四大组件的这些类的classLoader）</p>
<img lazyload="" src="/images/loading.svg" data-src="/2023/08/24/%E5%8A%A0%E5%A3%B3APP%E8%BF%90%E8%A1%8C%E6%B5%81%E7%A8%8B%E5%92%8CClassLoader%E4%BF%AE%E6%AD%A3/image-20230824222103300.png" class="" title="image-20230824222103300"></li>
</ol>
<h4 id="接下来写代码去加载dex中的Activity"><a href="#接下来写代码去加载dex中的Activity" class="headerlink" title="接下来写代码去加载dex中的Activity"></a>接下来写代码去加载dex中的Activity</h4><ul>
<li><p>如果继续按照上一节相同的代码去加载Activity的话会出现找不到dex中的方法的问题，无法启动我们的目标Activity</p>
</li>
<li><p>这个问题有两个解决方案：</p>
<ol>
<li><p><strong>替换</strong>系统组件的类加载器为我们的DexClassloader，同时设置DexClassLoader的parent节点为系统组件类加载器也就是pathClassLoader</p>
<img lazyload="" src="/images/loading.svg" data-src="/2023/08/24/%E5%8A%A0%E5%A3%B3APP%E8%BF%90%E8%A1%8C%E6%B5%81%E7%A8%8B%E5%92%8CClassLoader%E4%BF%AE%E6%AD%A3/image-20230824223243415.png" class="" title="image-20230824223243415">
</li>
<li><p>打破原有的双亲关系，在系统组件类加载器和BootClassLoader的中间<em>插入</em>我们自己的DexClassLoader</p>
<ul>
<li><p>这种方法和双亲委派密切相关，不替换原来组件的mClassLoader，保持原来的mClassLoader。但是呢如果再当前app进程的BootClassLoader和PathClassLoader之间插入我们的dexClassLoader，那在接下来启动其它的组件的时候，就会由于双亲委派虽然找不到pathClassLoader但是它的父节点是能找得到的。这种方法不需要通过繁琐的反射过程一步一步找到主键的mClassLoader。</p>
<img lazyload="" src="/images/loading.svg" data-src="/2023/08/24/%E5%8A%A0%E5%A3%B3APP%E8%BF%90%E8%A1%8C%E6%B5%81%E7%A8%8B%E5%92%8CClassLoader%E4%BF%AE%E6%AD%A3/image-20230824223416570.png" class="" title="image-20230824223416570"></li>
</ul>
</li>
</ol>
<h5 id="第一种解决方法的代码：load03-java"><a href="#第一种解决方法的代码：load03-java" class="headerlink" title="第一种解决方法的代码：load03_java"></a>第一种解决方法的代码：<strong>load03_java</strong></h5><pre><code class="java">package com.kanxue.load03_java;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.util.ArrayMap;
import android.util.Log;

import java.io.File;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import android.Manifest;

import dalvik.system.DexClassLoader;

public class MainActivity extends AppCompatActivity {

    private static final int PERMISSION_REQUEST_CODE = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 检查是否已经获得外部存储权限
        if (Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.M) {
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                // 请求权限
                ActivityCompat.requestPermissions(this,
                        new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
                        PERMISSION_REQUEST_CODE);
            } else {
                // 已经有权限，执行操作
                performAction();
            }
        }
    }

    // 处理权限请求结果
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == PERMISSION_REQUEST_CODE) {
            if (grantResults.length &gt; 0 &amp;&amp; grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // 用户授予了权限，执行操作
                performAction();
            } else {
                // 用户拒绝了权限，可以做一些处理，比如显示一个提示信息
                Log.d("Permission", "External storage permission denied");
            }
        }
    }

    // 在获得权限后执行的操作
    private void performAction() {
        // 在这里执行加载DEX文件并启动Activity的操作
        startTestActivity(this, "/sdcard/4.dex");
    }

    // 用于替换类加载器的方法
    public void replaceClassLoader(ClassLoader classLoader) {
        try {
            // 加载 android.app.ActivityThread 类
            Class&lt;?&gt; ActivityThreadClazz = classLoader.loadClass("android.app.ActivityThread");

            // 获取 currentActivityThread 静态方法
            Method currentActivityThreadMethod = ActivityThreadClazz.getDeclaredMethod("currentActivityThread");
            currentActivityThreadMethod.setAccessible(true);

            // 调用 currentActivityThread 方法，获取 ActivityThread 实例
            Object activityThread = currentActivityThreadMethod.invoke(null);

            // 获取 ActivityThread 类中的 mPackages 字段
            // final ArrayMap&lt;String, WeakReference&lt;LoadedApk&gt;&gt; mPackages = new ArrayMap&lt;&gt;();
            Field mPackagesField = ActivityThreadClazz.getDeclaredField("mPackages");
            mPackagesField.setAccessible(true);

            // 获取 mPackages 字段在 activityThread 实例中的值，它是一个 ArrayMap 对象
            ArrayMap mPackagesObj = (ArrayMap) mPackagesField.get(activityThread);

            // 从 mPackages 中获取对当前应用程序包的 WeakReference 引用
            WeakReference wr = (WeakReference) mPackagesObj.get(this.getPackageName());

            // 获取 WeakReference 中的实际对象，这是 LoadedApk 类的一个实例
            Object loadApkObj = wr.get();

            // 加载 android.app.LoadedApk 类
            Class loadedApkClazz = classLoader.loadClass("android.app.LoadedApk");

            // 获取 LoadedApk 类中的 mClassLoader 字段
            //private ClassLoader mClassLoader;
            Field mClassLoaderField = loadedApkClazz.getDeclaredField("mClassLoader");
            mClassLoaderField.setAccessible(true);

            // 将 LoadedApk 实例的 mClassLoader 字段设置为传入的类加载器
            mClassLoaderField.set(loadApkObj, classLoader);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    public void startTestActivity(Context context, String dexfilepath) {
        // 获取应用的私有目录，用于加载DEX文件和库文件
        File optfile = context.getDir("opt_dex", 0);
        File libfile = context.getDir("lib_path", 0);

        // 获取主Activity的类加载器和上下文的类加载器
        ClassLoader parentClassloader = MainActivity.class.getClassLoader();
        ClassLoader tmpClassloader = context.getClassLoader();

        // 创建一个DexClassLoader，用于加载DEX文件中的类
        DexClassLoader dexClassLoader = new DexClassLoader(
                dexfilepath,
                optfile.getAbsolutePath(),
                libfile.getAbsolutePath(),
                MainActivity.class.getClassLoader());

        // 替换类加载器，使外部类能够在应用中被访问
        replaceClassLoader(dexClassLoader);

        Class&lt;?&gt; clazz = null;
        try {
            // 从DEX文件加载指定的类
            clazz = dexClassLoader.loadClass("com.kanxue.test01_java.TestActivity");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        // 启动加载的外部Activity
        context.startActivity(new Intent(context, clazz));
    }
}
</code></pre>
<p><strong>test01_java</strong></p>
<pre><code class="java">package com.kanxue.test01_java;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;

import androidx.appcompat.app.AppCompatActivity;

public class TestActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // setContentView(R.layout.activity_main);
        Log.i("xiaoeryu","i am TestActivity.onCreate");
    }
}
</code></pre>
<p><strong>执行结果</strong></p>
<img lazyload="" src="/images/loading.svg" data-src="/2023/08/24/%E5%8A%A0%E5%A3%B3APP%E8%BF%90%E8%A1%8C%E6%B5%81%E7%A8%8B%E5%92%8CClassLoader%E4%BF%AE%E6%AD%A3/image-20230824223613663.png" class="" title="image-20230824223613663">

<h5 id="第二种解决方法：load04"><a href="#第二种解决方法：load04" class="headerlink" title="第二种解决方法：load04"></a>第二种解决方法：<strong>load04</strong></h5><pre><code class="java">package com.kanxue.load04;

import androidx.annotation.NonNull;
import android.app.Activity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;

import java.io.File;
import java.lang.reflect.Field;

import android.Manifest;

import dalvik.system.DexClassLoader;

public class MainActivity extends Activity {

    private static final int PERMISSION_REQUEST_CODE = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 检查是否已经获得外部存储权限
        if (Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.M) {
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                // 请求权限
                ActivityCompat.requestPermissions(this,
                        new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
                        PERMISSION_REQUEST_CODE);
            } else {
                // 已经有权限，执行操作
                performAction();
            }
        }
    }

    // 处理权限请求结果
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == PERMISSION_REQUEST_CODE) {
            if (grantResults.length &gt; 0 &amp;&amp; grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // 用户授予了权限，执行操作
                performAction();
            } else {
                // 用户拒绝了权限，可以做一些处理，比如显示一个提示信息
                Log.d("Permission", "External storage permission denied");
            }
        }
    }

    // 在获得权限后执行的操作
    private void performAction() {
        // 在这里执行加载DEX文件并启动Activity的操作
        startTestActivitySecondlyMethod(this, "/sdcard/5.dex");
    }

    // 使用第二种方法启动测试Activity
    public void startTestActivitySecondlyMethod(Context context, String dexFilePath) {
        // 获取应用程序的私有目录，用于存放优化后的DEX文件和本地库
        File optDir = context.getDir("opt_dex", 0);
        File libDir = context.getDir("lib_path", 0);

        // 获取系统类加载器和引导类加载器
        ClassLoader pathClassLoader = MainActivity.class.getClassLoader();
        ClassLoader bootClassLoader = MainActivity.class.getClassLoader().getParent();

        // 创建DexClassLoader来加载外部的DEX文件
        DexClassLoader dexClassLoader = new DexClassLoader(
                dexFilePath,                  // DEX文件路径
                optDir.getAbsolutePath(),     // 优化后的DEX文件存放目录
                libDir.getAbsolutePath(),     // 本地库存放目录
                bootClassLoader);             // 引导类加载器作为父加载器

        try {
            // 使用反射设置系统类加载器的父加载器为DexClassLoader
            Field parentField = ClassLoader.class.getDeclaredField("parent");
            parentField.setAccessible(true);
            parentField.set(pathClassLoader, dexClassLoader);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

        Class&lt;?&gt; clazz = null;
        try {
            // 加载外部DEX文件中的类
            clazz = dexClassLoader.loadClass("com.xiaoeryu.test04.TestActivity");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        // 启动外部加载的Activity
        context.startActivity(new Intent(context, clazz));
    }
}
</code></pre>
<p><strong>test04</strong></p>
<pre><code class="java">package com.xiaoeryu.test04;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;

public class TestActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        Log.i("xiaoeryu", "i am from TestActivity.onCreate");
    }
}
</code></pre>
<ul>
<li><p>这个代码除了要注意前面的几点之外还要把constraintlayout降一下级，不然运行的时候会有库版本冲突的问题</p>
<img lazyload="" src="/images/loading.svg" data-src="/2023/08/24/%E5%8A%A0%E5%A3%B3APP%E8%BF%90%E8%A1%8C%E6%B5%81%E7%A8%8B%E5%92%8CClassLoader%E4%BF%AE%E6%AD%A3/image-20230824223840687.png" class="" title="image-20230824223840687">
</li>
<li><p>这两种方案都可以解决加载dex中Activity的问题，相对来说第一种再加壳厂商中比较常用，通过替换app组件的ClassLoader: mClassLoader来实现，让插件类具有生命周期。这两种方案都要用大量的反射相关的api来实现。</p>
</li>
</ul>
</li>
</ul>
<h5 id="动态调试"><a href="#动态调试" class="headerlink" title="动态调试"></a>动态调试</h5><p>在插入DexClassLoader的代码后面，插入log看一下双亲委派的调用关系</p>
<pre><code class="java">        // 看一下双亲委派的调用关系
        ClassLoader tmpClassLoader = pathClassloader;
        ClassLoader parentClassLoader = pathClassloader.getParent();
        while (parentClassLoader != null){
            Log.i("xiaoeryu", "当前节点: " + tmpClassLoader + "--父节点: " + parentClassLoader);
            tmpClassLoader = parentClassLoader;
            parentClassLoader = parentClassLoader.getParent();
        }
        Log.i("xiaoeryu", "根节点: " + tmpClassLoader);
</code></pre>
<p><strong>运行结果</strong></p>
<pre><code>当前节点: dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.kanxue.load04-zqQtFmn29CDDYSwO8gpsPQ==/base.apk"],nativeLibraryDirectories=[/data/app/com.kanxue.load04-zqQtFmn29CDDYSwO8gpsPQ==/lib/arm64, /system/lib64, /vendor/lib64]]]--父节点: dalvik.system.DexClassLoader[DexPathList[[dex file "/sdcard/5.dex"],nativeLibraryDirectories=[/data/user/0/com.kanxue.load04/app_lib_path, /system/lib64, /vendor/lib64]]]
当前节点: dalvik.system.DexClassLoader[DexPathList[[dex file "/sdcard/5.dex"],nativeLibraryDirectories=[/data/user/0/com.kanxue.load04/app_lib_path, /system/lib64, /vendor/lib64]]]--父节点: java.lang.BootClassLoader@118830f
根节点: java.lang.BootClassLoader@118830f
</code></pre>
<p>题外话：</p>
<p>对于用户提交的一个带加固的app之后呢，加固厂商一般分两种情况去处理：</p>
<ol>
<li>这个app的AndroidManifest.xml当中没有声明这个application的话，处理起来较为简单一些，加固厂商只需要添加一个application就可以了，然后在这个application里面完成一些classloader的替换</li>
<li>如果已经有application的话呢，就需要一个代理的application。这种情况下壳的application不仅要完成解密dex以及classloader的一些相关修复还要完成解密dex之后原来application中两个函数（attachBaseContext和onCreate）的调用</li>
</ol>
<p>参考文章：<a class="link" target="_blank" rel="noopener" href="https://bbs.kanxue.com/thread-252630.htm#msg_header_h2_1">FART：ART环境下基于主动调用的自动化脱壳方案<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a></p>

		</div>

		
		<div class="post-copyright-info w-full my-8 px-2 sm:px-6 md:px-8">
			<div class="article-copyright-info-container">
    <ul>
        <li><strong>标题:</strong> 加壳APP运行流程和ClassLoader修正</li>
        <li><strong>作者:</strong> xiaoeryu</li>
        <li><strong>创建于
                :</strong> 2023-08-24 16:41:02</li>
        
            <li>
                <strong>更新于
                    :</strong> 2023-08-26 22:39:52
            </li>
        
        <li>
            <strong>链接:</strong> https://github.com/xiaoeryu/2023/08/24/加壳APP运行流程和ClassLoader修正/
        </li>
        <li>
            <strong>
                版权声明:
            </strong>
            

            
                本文章采用 <a class="license" target="_blank" rel="noopener" href="https://creativecommons.org/licenses/by-nc-sa/4.0">CC BY-NC-SA 4.0</a> 进行许可。
            
        </li>
    </ul>
</div>

		</div>
		

		
		<ul class="post-tags-box text-lg mt-1.5 flex-wrap justify-center flex md:hidden">
			
			<li class="tag-item mx-0.5">
				<a href="/tags/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/">#学习笔记</a>&nbsp;
			</li>
			
			<li class="tag-item mx-0.5">
				<a href="/tags/Android%E5%8A%A0%E5%A3%B3/">#Android加壳</a>&nbsp;
			</li>
			
			<li class="tag-item mx-0.5">
				<a href="/tags/%E5%8A%A0%E5%A3%B3%E5%92%8C%E8%BF%90%E8%A1%8C%E6%97%B6%E7%9A%84%E6%9C%BA%E5%88%B6/">#加壳和运行时的机制</a>&nbsp;
			</li>
			
		</ul>
		

		

		
		<div class="article-nav my-8 flex justify-between items-center px-2 sm:px-6 md:px-8">
			
			<div class="article-prev border-border-color shadow-redefine-flat shadow-shadow-color-2 rounded-medium px-4 py-2 hover:shadow-redefine-flat-hover hover:shadow-shadow-color-2">
				<a class="prev" rel="prev" href="/2023/08/26/%E4%B8%80%E4%BA%8C%E4%B8%89%E4%BB%A3%E5%A3%B3%E5%92%8C%E5%A3%B3%E6%8A%80%E6%9C%AF%E5%88%86%E7%B1%BB%E8%AF%86%E5%88%AB/">
					<span class="left arrow-icon flex justify-center items-center">
						<i class="fa-solid fa-chevron-left"></i>
					</span>
					<span class="title flex justify-center items-center">
						<span class="post-nav-title-item">一二三代壳和壳技术分类识别</span>
						<span class="post-nav-item">上一篇</span>
					</span>
				</a>
			</div>
			
			
			<div class="article-next border-border-color shadow-redefine-flat shadow-shadow-color-2 rounded-medium px-4 py-2 hover:shadow-redefine-flat-hover hover:shadow-shadow-color-2">
				<a class="next" rel="next" href="/2023/08/19/ClassLoader%E5%92%8C%E5%8A%A8%E6%80%81%E5%8A%A0%E8%BD%BD/">
					<span class="title flex justify-center items-center">
						<span class="post-nav-title-item">ClassLoader和动态加载</span>
						<span class="post-nav-item">下一篇</span>
					</span>
					<span class="right arrow-icon flex justify-center items-center">
						<i class="fa-solid fa-chevron-right"></i>
					</span>
				</a>
			</div>
			
		</div>
		


		
		<div class="comment-container px-2 sm:px-6 md:px-8 pb-8">
			<div class="comments-container mt-10 w-full ">
    <div id="comment-anchor" class="w-full h-2.5"></div>
    <div class="comment-area-title w-full my-1.5 md:my-2.5 text-xl md:text-3xl font-bold">
        评论
    </div>
    

        
            


        
    
</div>

		</div>
		
	</div>

	
	<div class="toc-content-container">
		<div class="post-toc-wrap">
	<div class="post-toc">
		<div class="toc-title">目录</div>
		<div class="page-title">加壳APP运行流程和ClassLoader修正</div>
		<ol class="nav"><li class="nav-item nav-level-3"><a class="nav-link" href="#app%E5%90%AF%E5%8A%A8%E6%B5%81%E7%A8%8B"><span class="nav-text">app启动流程</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#ActivityThread%E7%9A%84%E6%BA%90%E4%BB%A3%E7%A0%81"><span class="nav-text">ActivityThread的源代码</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#APP%E5%8A%A0%E5%A3%B3%E5%8E%9F%E7%90%86%E4%BB%A5%E5%8F%8A%E8%BF%90%E8%A1%8C%E6%B5%81%E7%A8%8B"><span class="nav-text">APP加壳原理以及运行流程</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%88%86%E6%9E%90%E6%BA%90%E7%A0%81%E5%B9%B6%E5%86%99%E4%BB%A3%E7%A0%81%E5%8A%A0%E8%BD%BD%E5%85%B6%E5%AE%83dex%E4%B8%ADActivity"><span class="nav-text">分析源码并写代码加载其它dex中Activity</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%8E%A5%E4%B8%8B%E6%9D%A5%E5%86%99%E4%BB%A3%E7%A0%81%E5%8E%BB%E5%8A%A0%E8%BD%BDdex%E4%B8%AD%E7%9A%84Activity"><span class="nav-text">接下来写代码去加载dex中的Activity</span></a></li></ol></li></ol>

	</div>
</div>
	</div>
	
</div>
			</div>

			
		</div>

		<div class="main-content-footer">
			<footer class="footer mt-5 py-5 h-auto text-base text-third-text-color relative border-t-2 border-t-border-color">
    <div class="info-container py-3 text-center">
        
        <div class="text-center">
            &copy;
            
              <span>2022</span>
              -
            
            2025&nbsp;&nbsp;<i class="fa-solid fa-heart fa-beat" style="--fa-animation-duration: 0.5s; color: #f54545"></i>&nbsp;&nbsp;<a href="/">xiaoeryu</a>
            
                
                <p class="post-count space-x-0.5">
                    <span>
                        共撰写了 112 篇文章
                    </span>
                    
                </p>
            
        </div>
        
            <script data-swup-reload-script src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
            <div class="relative text-center lg:absolute lg:right-[20px] lg:top-1/2 lg:-translate-y-1/2 lg:text-right">
                
                    <span id="busuanzi_container_site_uv" class="lg:!block">
                        <span class="text-sm">访问人数</span>
                        <span id="busuanzi_value_site_uv"></span>
                    </span>
                
                
                    <span id="busuanzi_container_site_pv" class="lg:!block">
                        <span class="text-sm">总访问量</span>
                        <span id="busuanzi_value_site_pv"></span>
                    </span>
                
            </div>
        
        <div class="relative text-center lg:absolute lg:left-[20px] lg:top-1/2 lg:-translate-y-1/2 lg:text-left">
            <span class="lg:block text-sm">由 <?xml version="1.0" encoding="utf-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="relative top-[2px] inline-block align-baseline" version="1.1" id="圖層_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="1rem" height="1rem" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve"><path fill="#0E83CD" d="M256.4,25.8l-200,115.5L56,371.5l199.6,114.7l200-115.5l0.4-230.2L256.4,25.8z M349,354.6l-18.4,10.7l-18.6-11V275H200v79.6l-18.4,10.7l-18.6-11v-197l18.5-10.6l18.5,10.8V237h112v-79.6l18.5-10.6l18.5,10.8V354.6z"/></svg><a target="_blank" class="text-base" href="https://hexo.io">Hexo</a> 驱动</span>
            <span class="text-sm lg:block">主题&nbsp;<a class="text-base" target="_blank" href="https://github.com/EvanNotFound/hexo-theme-redefine">Redefine v2.8.2</a></span>
        </div>
        
        
            <div>
                博客已运行 <span class="odometer" id="runtime_days" ></span> 天 <span class="odometer" id="runtime_hours"></span> 小时 <span class="odometer" id="runtime_minutes"></span> 分钟 <span class="odometer" id="runtime_seconds"></span> 秒
            </div>
        
        
            <script data-swup-reload-script>
                try {
                    function odometer_init() {
                    const elements = document.querySelectorAll('.odometer');
                    elements.forEach(el => {
                        new Odometer({
                            el,
                            format: '( ddd).dd',
                            duration: 200
                        });
                    });
                    }
                    odometer_init();
                } catch (error) {}
            </script>
        
        
        
    </div>  
</footer>
		</div>
	</div>

	
	<div class="post-tools">
		<div class="post-tools-container">
	<ul class="article-tools-list">
		<!-- TOC aside toggle -->
		
		<li class="right-bottom-tools page-aside-toggle">
			<i class="fa-regular fa-outdent"></i>
		</li>
		

		<!-- go comment -->
		
		<li class="go-comment">
			<i class="fa-regular fa-comments"></i>
		</li>
		
	</ul>
</div>
	</div>
	

	<div class="right-side-tools-container">
		<div class="side-tools-container">
	<ul class="hidden-tools-list">
		<li class="right-bottom-tools tool-font-adjust-plus flex justify-center items-center">
			<i class="fa-regular fa-magnifying-glass-plus"></i>
		</li>

		<li class="right-bottom-tools tool-font-adjust-minus flex justify-center items-center">
			<i class="fa-regular fa-magnifying-glass-minus"></i>
		</li>

		<li class="right-bottom-tools tool-dark-light-toggle flex justify-center items-center">
			<i class="fa-regular fa-moon"></i>
		</li>

		<!-- rss -->
		

		

		<li class="right-bottom-tools tool-scroll-to-bottom flex justify-center items-center">
			<i class="fa-regular fa-arrow-down"></i>
		</li>
	</ul>

	<ul class="visible-tools-list">
		<li class="right-bottom-tools toggle-tools-list flex justify-center items-center">
			<i class="fa-regular fa-cog fa-spin"></i>
		</li>
		
		<li class="right-bottom-tools tool-scroll-to-top flex justify-center items-center">
			<i class="arrow-up fas fa-arrow-up"></i>
			<span class="percent"></span>
		</li>
		
		
	</ul>
</div>
	</div>

	<div class="image-viewer-container">
	<img src="">
</div>

	
	<div class="search-pop-overlay">
	<div class="popup search-popup">
		<div class="search-header">
			<span class="search-input-field-pre">
				<i class="fa-solid fa-keyboard"></i>
			</span>
			<div class="search-input-container">
				<input autocomplete="off" autocorrect="off" autocapitalize="off" placeholder="站内搜索您需要的内容..." spellcheck="false" type="search" class="search-input">
			</div>
			<span class="popup-btn-close">
				<i class="fa-solid fa-times"></i>
			</span>
		</div>
		<div id="search-result">
			<div id="no-result">
				<i class="fa-solid fa-spinner fa-spin-pulse fa-5x fa-fw"></i>
			</div>
		</div>
	</div>
</div>
	

</main>



<script src="/js/build/libs/Swup.min.js"></script>

<script src="/js/build/libs/SwupSlideTheme.min.js"></script>

<script src="/js/build/libs/SwupScriptsPlugin.min.js"></script>

<script src="/js/build/libs/SwupProgressPlugin.min.js"></script>

<script src="/js/build/libs/SwupScrollPlugin.min.js"></script>

<script src="/js/build/libs/SwupPreloadPlugin.min.js"></script>

<script>
    const swup = new Swup({
        plugins: [
            new SwupScriptsPlugin({
                optin: true,
            }),
            new SwupProgressPlugin(),
            new SwupScrollPlugin({
                offset: 80,
            }),
            new SwupSlideTheme({
                mainElement: ".main-content-body",
            }),
            new SwupPreloadPlugin(),
        ],
        containers: ["#swup"],
    });
</script>




	
<script src="/js/build/tools/imageViewer.js" type="module"></script>

<script src="/js/build/utils.js" type="module"></script>

<script src="/js/build/main.js" type="module"></script>

<script src="/js/build/layouts/navbarShrink.js" type="module"></script>

<script src="/js/build/tools/scrollTopBottom.js" type="module"></script>

<script src="/js/build/tools/lightDarkSwitch.js" type="module"></script>

<script src="/js/build/layouts/categoryList.js" type="module"></script>



    
<script src="/js/build/tools/localSearch.js" type="module"></script>




    
<script src="/js/build/tools/codeBlock.js" type="module"></script>




    
<script src="/js/build/layouts/lazyload.js" type="module"></script>




    
<script src="/js/build/tools/runtime.js"></script>

    
<script src="/js/build/libs/odometer.min.js"></script>

    
<link rel="stylesheet" href="/assets/odometer-theme-minimal.css">




  
<script src="/js/build/libs/Typed.min.js"></script>

  
<script src="/js/build/plugins/typed.js" type="module"></script>








    
<script src="/js/build/libs/anime.min.js"></script>





    
<script src="/js/build/tools/tocToggle.js" type="module" data-swup-reload-script=""></script>

<script src="/js/build/layouts/toc.js" type="module" data-swup-reload-script=""></script>

<script src="/js/build/plugins/tabs.js" type="module" data-swup-reload-script=""></script>




<script src="/js/build/libs/moment-with-locales.min.js" data-swup-reload-script=""></script>


<script src="/js/build/layouts/essays.js" type="module" data-swup-reload-script=""></script>





	
</body>

</html>